package com.zhanglinfeng.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.zhanglinfeng.api.enums.ResultCode;
import com.zhanglinfeng.api.exception.CustomException;
import com.zhanglinfeng.api.response.ResultResponse;
import com.zhanglinfeng.api.util.GsonUtil;
import com.zhanglinfeng.api.util.TokenUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class AuthenticationFilter extends ZuulFilter {

    @Override
    public String filterType() {
        //fiterType,有pre、route、post、error四种类型，分别代表路由前、路由时
        //路由后以及异常时的过滤器
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //排序，指定相同filterType时的执行顺序，越小越优先执行，这里指定顺序为路由过滤器的顺序-1，即在路由前执行
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        //是否应该调用run()方法
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        ResultResponse<?> result = new ResultResponse();

        RequestContext ctx = RequestContext.getCurrentContext();

        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        String url = request.getRequestURI();
        if (url.contains("/api/")) {
            String token = request.getHeader("Authentication");
            if (StringUtils.isBlank(token)) {
                // 返回错误内容
                result.setCode(500);
                result.setMessage("该api需要token访问");

                setCtx(ctx, false, 500, GsonUtil.gson.toJson(result));

                return null;
            }

            //校验token正确性
            try {
                TokenUtil.parseJWT(token);
            } catch (CustomException e) {
                ResultCode resultCode = e.getResultCode();
                int code = resultCode.getCode();

                // 返回错误内容
                result.setCode(code);
                result.setMessage(resultCode.getMsg());

                setCtx(ctx, false, code, GsonUtil.gson.toJson(result));
            }
            return null;
        }

        return true;
    }

    private static void setCtx(RequestContext ctx, boolean expression, int statusCode, String jsonBody) {
        ctx.setSendZuulResponse(expression);
        // 返回错误码
        ctx.setResponseStatusCode(statusCode);
        ctx.set("isSuccess", expression);
        ctx.setResponseBody(jsonBody);
    }
}
